package com.ccp.dev.qbdms.util;

import static com.ccp.dev.system.service.SysFileService.getBasePath;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ccp.dev.core.basic.util.PropertyUtil;
import com.ccp.dev.core.util.AppUtil;
import com.ccp.dev.extend.model.ExtendSysFile;
import com.ccp.dev.extend.service.ExtendAttachmentSysFileService;
import com.ccp.dev.qbdms.annotation.IsAttachment;
import com.ccp.dev.qbdms.consts.ZhiLiangConst;
import com.ccp.dev.qbdms.webservice.cxf.CxfClient;
import com.google.common.collect.Lists;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.BASE64Decoder;

/**
 * ClassDescribe:
 *
 * @author :milihao
 * @date :2020-08-17 Since:1
 */
public class ReadAttachmentUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(ReadAttachmentUtil.class);


    /**
     * 将字符串存储为文件 采用Base64解码
     *
     * @param inputStream 文件流
     * @param outFileStr  输出文件路径
     */
    public static void streamSaveAsFile(InputStream inputStream, String outFileStr) {
        FileOutputStream fos = null;
        try {
            File file = new File(outFileStr);
            // 路径为文件且不为空则进行删除
            if (file.isFile() && file.exists()) {
                file.delete();
            }
            BASE64Decoder decoder = new BASE64Decoder();
            fos = new FileOutputStream(file);
            byte[] buffer = decoder.decodeBuffer(inputStream);
            fos.write(buffer, 0, buffer.length);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            try {
                inputStream.close();
                fos.close();
            } catch (Exception e2) {
                e2.printStackTrace();
                throw new RuntimeException(e2);
            }
        }
    }

    /**
     * 将字符串存储为文件
     *
     * @param fileStr     文件流字符串
     * @param outFilePath 输出地址
     */
    public static void stringSaveAsFile(String fileStr, String outFilePath) {
        InputStream out = new ByteArrayInputStream(fileStr.getBytes());
        ReadAttachmentUtil.streamSaveAsFile(out, outFilePath);
    }

    /**
     * 将流转换成字符串 使用Base64加密
     *
     * @param inputStream 文件流
     */
    public static String streamToString(InputStream inputStream) throws IOException {
        byte[] bt = toByteArray(inputStream);
        inputStream.close();
        String out = new sun.misc.BASE64Encoder().encodeBuffer(bt);
        return out;
    }

    /**
     * 将流转换成字符串
     *
     * @param filePath 文件路径
     */
    public static String fileToString(String filePath) throws IOException {
        File file = new File(filePath);
        if (!file.exists()) {
            LOGGER.error("ReadAttachmentUtil-fileToString-file not fond and filePath is :" + filePath);
            return null;
        }
        FileInputStream is = new FileInputStream(file);
        return ReadAttachmentUtil.streamToString(is);
    }

    /**
     * 将流转化为字节数组
     *
     * @param inputStream 文件流
     */
    public static byte[] toByteArray(InputStream inputStream) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024 * 4];
        byte[] result = null;
        try {
            int n = 0;
            while ((n = inputStream.read(buffer)) != -1) {
                out.write(buffer, 0, n);
            }
            result = out.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            out.close();
        }
        return result;
    }


    /**
     * 获取上报的file
     *
     * @param paramMap  参数map
     * @param modelName 类名称
     * @return List<ExtendSysFile>
     */
    public static List<ExtendSysFile> getReport(Map<String, Object> paramMap, String modelName) {
        JSONObject jsonObj = JSONObject.parseObject(
                JSON.toJSONString(paramMap));
        // 获取上报参数,是一个list
        JSONArray listObj = jsonObj.getJSONArray(ZhiLiangConst.API_REPORT_PARA_LIST);
        modelName = CxfClient.getClassName(modelName);
        Class<?> clazz1 = null;
        try {
            clazz1 = Class.forName("com.ccp.dev.qbdms.model." + modelName);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        List<?> list = listObj.toJavaList(clazz1);
        List<ExtendSysFile> extendSysFileList = getExtendSysFileList(list);
        return extendSysFileList;

    }

    /**
     * 获取fileList
     *
     * @param list list
     * @param <T> T
     * @return List<SysFile>
     */
    public static <T> List<ExtendSysFile> getExtendSysFileList(List<T> list) {
        List<ExtendSysFile> extendSysFileList = Lists.newArrayList();
        for (T t : list) {
            packageExtendSysFileList(t, extendSysFileList);
        }
        return extendSysFileList;
    }

    public static <T> T packageExtendSysFileList(T t, List<ExtendSysFile> extendSysFileList) {
        Field[] fields = t.getClass().getDeclaredFields();
        for (Field field : fields) {
            if (field.isAnnotationPresent(IsAttachment.class)) {
                field.setAccessible(true);
                String value = null;
                try {
                    if (null == field.get(t)) {
                        continue;
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                IsAttachment isAttachment = field.getAnnotation(IsAttachment.class);
                if (isAttachment.isSubTable()) {
                    try {
                        List<T> tList = (List) field.get(t);
                        for (T t1 : tList) {
                            packageExtendSysFileList(t1, extendSysFileList);
                        }
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                } else {
                    try {
                        value = (String) field.get(t);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                    List<Map> mapList = JSON.parseArray(value, Map.class);
                    getExtendSysFileList(mapList, extendSysFileList);
                }
            }
        }
        return t;
    }

    /**
     * 根据FileId获取file
     *
     * @param mapList fileId
     * @param extendSysFileList fileList
     * @return List<SysFile>
     */
    private static List<ExtendSysFile> getExtendSysFileList(List<Map> mapList,
        List<ExtendSysFile> extendSysFileList) {
        ExtendAttachmentSysFileService extendAttachmentSysFileService = AppUtil
            .getBean(ExtendAttachmentSysFileService.class);
        ExtendSysFile extendSysFile;
        if (null != mapList) {
            for (Map<String, Object> map : mapList) {
                if (null != map.get("fileId")) {
                    extendSysFile = extendAttachmentSysFileService
                        .getOneById(String.valueOf(map.get("fileId")));
                    try {
                        extendSysFile.setAttachmentStrContent(ReadAttachmentUtil
                            .fileToString(
                                getBasePath().replace("/", File.separator) + "/" + extendSysFile
                                    .getFilePath()));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    extendSysFileList.add(extendSysFile);
                }
            }
        }
        return extendSysFileList;
    }


    /**
     * 保存附件
     *
     * @param list              实体List
     * @param extendSysFileList 文件流List
     * @param <T>               实体
     * @return List<T>
     */
    public static <T> List<T> getEntityData(List<T> list, List<ExtendSysFile> extendSysFileList) {
        try {
            for (T t : list) {
                Field[] fields = t.getClass().getDeclaredFields();
                for (Field field : fields) {
                    if (field.isAnnotationPresent(IsAttachment.class)) {
                        field.setAccessible(true);
                        String value = null;
                        try {
                            if (null == field.get(t)) {
                                continue;
                            }
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                        IsAttachment isAttachment = field.getAnnotation(IsAttachment.class);
                        if (isAttachment.isSubTable()) {
                            try {
                                List<T> tList = (List) field.get(t);
                                getEntityData(tList, extendSysFileList);
                            } catch (IllegalAccessException e) {
                                e.printStackTrace();
                            }
                        } else {
                            try {
                                value = (String) field.get(t);
                            } catch (IllegalAccessException e) {
                                e.printStackTrace();
                            }
                            List<Map> mapList = JSON.parseArray(value, Map.class);
                            saveExtendSysFile(mapList, extendSysFileList);
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    private static void saveExtendSysFile(List<Map> mapList, List<ExtendSysFile> extendSysFileList) {
        ExtendAttachmentSysFileService extendAttachmentSysFileService = AppUtil.getBean(ExtendAttachmentSysFileService.class);
        if (null != mapList) {
            for (Map<String, Object> map : mapList) {
                if (null != map.get("fileId")) {
                    String fileId = String.valueOf(map.get("fileId"));
                    for (ExtendSysFile extendSysFile : extendSysFileList) {
                        if (extendSysFile.getFileId().equals(fileId)) {
                            String[] filePath;
                            if (isWindows()) {
                                filePath = extendSysFile.getFilePath().split("\\\\");
                            }
                            else {
                                filePath = extendSysFile.getFilePath().split("/");
                            }
                            String savePath = PropertyUtil.getByAlias("file.upload") + "/";
                            for (int i = 0; i < filePath.length - 1; i++) {
                                savePath += filePath[i] + "/";
                            }
                            File file = new File(savePath);
                            if (!file.exists()) {
                                File file1 = new File(savePath);
                                file1.mkdirs();
                            }
                            savePath += filePath[filePath.length - 1];
                            ReadAttachmentUtil
                                .stringSaveAsFile(extendSysFile.getAttachmentStrContent(),
                                    savePath);
                            extendSysFile.setAttachmentStrContent(null);
                            extendAttachmentSysFileService.delById(fileId);
                            extendAttachmentSysFileService.add(extendSysFile);
                        }
                    }
                }
            }
        }
    }

    public static boolean isWindows() {
        return System.getProperty("os.name").toLowerCase().contains("windows");
    }


}
